package com.neusoft.bizcore.auth.controller;

import java.util.List;
import java.util.stream.Collectors;

import org.hibernate.validator.constraints.Length;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Pageable;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.neusoft.bizcore.auth.common.bean.UserBean;
import com.neusoft.bizcore.auth.common.jwt.JwtAuthProvider;
import com.neusoft.bizcore.auth.dto.AuthUserCreateUpdateDTO;
import com.neusoft.bizcore.auth.dto.AuthUserDTO;
import com.neusoft.bizcore.auth.service.AuthUserService;
import com.neusoft.bizcore.web.constant.ExceptionConstants;
import com.neusoft.bizcore.web.dto.result.PageResultDTO;
import com.neusoft.bizcore.web.dto.result.ResultDTO;
import com.neusoft.bizcore.web.dto.result.ResultListDTO;
import com.neusoft.bizcore.web.support.Searchable;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;

@Api("用户管理")
@RestController
@RequestMapping(value = "/api/w/auth/users")
public class AuthUserController {

    @Autowired
    private AuthUserService authUserService;

    @ApiOperation("查询所有用户")
    @GetMapping
    public ResultListDTO<AuthUserDTO> index(final Searchable searchable) {
        final List<AuthUserDTO> DTOs = this.authUserService.findAll(searchable);
        final ResultListDTO<AuthUserDTO> result = ResultListDTO.success(DTOs);
        return result;
    }

    @ApiOperation("根据用户名查询用户详情（Security）")
    @GetMapping("/username/{username}")
    public ResultDTO<UserBean> loadUserByUsername(@PathVariable final String username) {
        final UserBean userBean = this.authUserService.loadUserByUsername(username);
        return ResultDTO.success(userBean);
    }

    @ApiOperation("分页查询所有用户")
    @GetMapping("/p")
    public PageResultDTO<AuthUserDTO> search(final Pageable pageable, final Searchable searchable) {
        return PageResultDTO.success(this.authUserService.search(pageable, searchable));
    }

    @ApiOperation("创建用户")
    @PostMapping
    public ResultDTO<AuthUserDTO> create(@RequestBody final AuthUserCreateUpdateDTO dto) {
        final AuthUserDTO result = this.authUserService.create(dto);
        return ResultDTO.success(result);
    }

    @ApiOperation("用户详情")
    @GetMapping("/me")
    public ResultDTO<UserBean> me(final UserBean userBean) {
        return ResultDTO.success(userBean);
    }

    @ApiOperation("免登录用户获取token")
    @GetMapping("/anonymous/{days}")
    public ResultDTO<String> anonymous(@PathVariable final int days) {
        final UserBean userBean = this.authUserService.loadUserByUsername("anonymous");
        final JwtAuthProvider jwtAuthProvider = new JwtAuthProvider(days * 24 * 60 * 60 * 1000, "secret");
        final String token = jwtAuthProvider.generateToken("anonymous",
                userBean.getRoles().stream().map(b -> b.getRole()).collect(Collectors.toList()));
        return ResultDTO.success(token);
    }

    @ApiOperation("用户详情(批量请求)")
    @GetMapping("/batchusers")
    public ResultListDTO<AuthUserDTO> batchDetails(@RequestParam(required = true) final List<String> usernames) {
        final List<AuthUserDTO> dUsers = this.authUserService.details(usernames);
        return ResultListDTO.success(dUsers);
    }

    @ApiOperation("用户详情")
    @GetMapping("/{id}")
    public ResultDTO<AuthUserDTO> details(@PathVariable final Long id) {
        final AuthUserDTO dto = this.authUserService.details(id);
        return ResultDTO.success(dto);
    }

    @ApiOperation("删除用户")
    @DeleteMapping("/{id}")
    public ResultDTO<Void> delete(@PathVariable final Long id) {
        this.authUserService.delete(id);
        return ResultDTO.success();
    }

    //    @ApiOperation("用户修改密码")
    //    @PutMapping("/changepass")
    //    public ResultDTO<Void> changeMyPass(final UserBean userBean, final ChangePasswordBean bean) {
    //        if ((userBean.getPassword() != null) & userBean.getPassword().equals(bean.getOldPassword())) {
    //            this.authUserService.resetPass(userBean.getUserId(), bean.getNewPassword());
    //        } else {
    //            throw new AccessDeniedException(ExceptionConstants.ACCESS_DENIED);
    //        }
    //        return ResultDTO.success();
    //    }

    @ApiOperation(value = "修改用户")
    @PutMapping("/{id}")
    public ResultDTO<AuthUserDTO> update(@PathVariable final Long id,
            @RequestBody final AuthUserCreateUpdateDTO dto) {
        final AuthUserDTO result = this.authUserService.update(id, dto);
        return ResultDTO.success(result);
    }

    @ApiOperation("修改密码")
    @PutMapping("/changepassword")
    public ResultDTO<String> changePassword(final UserBean operator,
            @Length(min = 6, max = 18, message = "6~18位密码") @RequestParam final String password,
            @Length(min = 6, max = 18, message = "6~18位密码") @RequestParam final String oldPassword) {
        if (!this.authUserService.checkOldPassword(operator.getUserId(), oldPassword)) {
            return ResultDTO.failure(ExceptionConstants.OLD_PASSWORD_ERROR);
        }
        this.authUserService.resetPass(operator.getUserId(), password);
        return ResultDTO.success("success");
    }

    @ApiOperation("重置密码")
    @PutMapping("/{id}/resetpassword")
    public ResultDTO<String> resetPassword(final UserBean operator, @PathVariable final Long id,
            @Length(min = 6, max = 18, message = "6~18位密码") @RequestParam final String password) {
        if (operator.getRoles().stream().filter(it -> "admin".equals(it.getRole())).count() > 0) {
            this.authUserService.resetPass(id, password);
            return ResultDTO.success("success");
        } else {
            return ResultDTO.failure(ExceptionConstants.ACCESS_DENIED);
        }
    }

}
